#include<iostream>
#include<vector>
#include<unordered_map>
#include<string>
#include<functional>
#include<memory>
#include<unistd.h>


using TaskFunc=std::function<void()>;
using RealseFunc=std::function<void()>;
class TimerTask
{
public:
      TimerTask(uint64_t id,uint32_t timeout,const TaskFunc& task_cb)
            :id_(id),timeout_(timeout),cancel_(false),task_cb_(task_cb)
      {}
      ~TimerTask()
      {
            if(cancel_==false)      task_cb_();
            realse_();
      }
public:
      void Cancel()     {cancel_=true;}
      void SetRealse(const RealseFunc& cb)      {realse_=cb;}  
      uint32_t DelayTime()    {return timeout_;}
private:
      uint64_t id_;                 //定时任务对象的id
      uint32_t timeout_;            //定时任务对象的超时时间
      bool cancel_;                 //false 表示没有被取消，true表示被取消
      TaskFunc task_cb_;            //定时任务要执行的回调任务
      RealseFunc realse_;           //用于删除tiemrwheel中保存的定时器对象信息
};

class TimerWheel
{
      using PtrTask=std::shared_ptr<TimerTask>;
      using WeakTask=std::weak_ptr<TimerTask>;
private:
      void RemoveTimer(uint64_t id)
      {
            auto it=timer_.find(id);
            if(it!=timer_.end())
                  timer_.erase(it);
      }
public:
      TimerWheel()
            :tick_(0),capacity_(60),wheel_(capacity_)
      {}
      void TimerAdd(uint64_t id,uint32_t delay,const TaskFunc& cb)
      {
            PtrTask ptr(new TimerTask(id,delay,cb));
            ptr->SetRealse(std::bind(&TimerWheel::RemoveTimer,this,id));
            int pos=(tick_+delay)%capacity_;
            wheel_[pos].push_back(ptr);
            timer_[id]=WeakTask(ptr);
      }
      //刷新延迟定时任务
      void TimerRefresh(uint64_t id)
      {
            //通过保存的定时器对象的weak_ptr来构造一个share_ptr 出来，添加到wheel中
            auto it=timer_.find(id);
            if(it==timer_.end())
                  return;
            PtrTask ptr=it->second.lock();
            uint32_t pos=(ptr->DelayTime()+tick_)%capacity_;
            wheel_[pos].push_back(ptr);
      }
      void TimerCancel(uint64_t id)
      {
            auto it=timer_.find(id);
            if(it==timer_.end())
                  return;
            PtrTask ptr=it->second.lock();
            if(ptr)
                  ptr->Cancel();
      }
      //这个函数每秒钟执行一次，相当于指针向后移动了一步
      void RunTimeTask()
      {
            tick_=(tick_+1)%capacity_;
            wheel_[tick_].clear();
      }
private:
      int tick_;                    //当前的秒钟，走到哪里，释放哪里，就相当于执行哪里的任务
      int capacity_;                //表盘的最大刻度，《==》 延迟的最大时间
      std::vector<std::vector<PtrTask>> wheel_;
      std::unordered_map<uint64_t,WeakTask> timer_;
};

class A
{
public:
      A(){std::cout<<"A 构造hanshu";}
      ~A(){std::cout<<"A 析构hanshu";}
};

void test(A* t)
{
      delete t;
      std::cout<<"delete ...........";
}


int main()
{
      A* a(new A);
      TimerWheel t;
      t.TimerAdd(888,4,std::bind(test,a));
      for(int i=0;i<4;i++)
      {
            sleep(1);
            t.TimerRefresh(888);
            t.RunTimeTask();
            std::cout<<"刷新了一下定时任务......4秒后运行"<<std::endl;
      }
      int count=0;
      while(1)
      {
            sleep(1);
            std::cout<<"count:"<<count++<<std::endl;
            t.RunTimeTask();
      }
      return 0;
}
